package com.doubao.wechat.service.impl;

import com.doubao.common.result.Result;
import com.doubao.common.utils.OrderNumberUtil;
import com.doubao.wechat.client.UserServiceClient;
import com.doubao.wechat.config.WxPayConfig;
import com.doubao.wechat.dto.request.WxPayOrderRequest;
import com.doubao.wechat.dto.response.UserInfoResponse;
import com.doubao.wechat.dto.response.WxPayOrderResponse;
import com.doubao.wechat.entity.PaymentOrder;
import com.doubao.wechat.mapper.PaymentOrderMapper;
import com.doubao.wechat.service.WxPayService;
import com.doubao.wechat.util.WxPaySignatureUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.security.PrivateKey;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * 微信支付服务实现类
 */
@Service
@Slf4j
public class WxPayServiceImpl implements WxPayService {
    private final WxPayConfig wxPayConfig;
    private final RestTemplate restTemplate;
    private final ObjectMapper objectMapper;
    private final PaymentOrderMapper paymentOrderMapper; // 添加这个依赖

    // 修改注入的客户端名称
    @Autowired
    private UserServiceClient userServiceClient; // 改为正确的客户端名称

    @Value("${wechat.miniapp.appid}")
    private String miniappAppid;

    @Value("${wechat.mp.appid}")
    private String mpAppid;

    // 微信支付接口URL
    private static final String CREATE_ORDER_URL = "/v3/pay/transactions/jsapi";
    private static final String QUERY_ORDER_URL = "/v3/pay/transactions/out-trade-no/%s";
    private static final String CLOSE_ORDER_URL = "/v3/pay/transactions/out-trade-no/%s/close";
    private static final String REFUND_URL = "/v3/refund/domestic/refunds";

    // 构造函数需要添加 PaymentOrderMapper 参数
    @Autowired
    public WxPayServiceImpl(
            WxPayConfig wxPayConfig,
            RestTemplate restTemplate,
            ObjectMapper objectMapper,
            PaymentOrderMapper paymentOrderMapper) {
        this.wxPayConfig = wxPayConfig;
        this.restTemplate = restTemplate;
        this.objectMapper = objectMapper;
        this.paymentOrderMapper = paymentOrderMapper; // 添加这行
    }

    @Override
    public Result<WxPayOrderResponse> createOrder(WxPayOrderRequest request) {
        try {
            // 确定使用的appid
            String appid = StringUtils.isNotBlank(request.getAppid()) ? request.getAppid() :
                    "jsapi".equalsIgnoreCase(request.getTradeType()) ? mpAppid : miniappAppid;

            // 检查 openid 是否为空，如果为空则尝试获取
            String openid = request.getOpenid();
            log.info("支付请求参数: outTradeNo={}, tradeType={}, openid={}, userId={}", 
                    request.getOutTradeNo(), request.getTradeType(), 
                    StringUtils.isBlank(openid) ? "未提供" : "已提供", request.getUserId());
                    
            if (StringUtils.isBlank(openid)) {
                if (request.getUserId() == null) {
                     log.error("创建订单失败：openid 和 userId 不能同时为空");
                    return Result.failed("创建订单失败：缺少支付用户信息(openid 或 userId)");
                }
                log.info("OpenID为空，尝试通过userId {} 和交易类型 {} 获取", request.getUserId(), request.getTradeType());
                openid = getOpenidByUserId(request.getUserId(), request.getTradeType()); // 根据支付类型获取对应openid
                if (StringUtils.isBlank(openid)) {
                    log.error("根据userId {} 和交易类型 {} 获取openid失败", request.getUserId(), request.getTradeType());
                    return Result.failed("获取用户微信openid失败，无法支付");
                }
                log.info("成功获取到 openid: {}, 交易类型: {}", openid, request.getTradeType());
            }

            // 组装支付请求参数
            Map<String, Object> requestMap = new HashMap<>();
            requestMap.put("appid", appid);
            requestMap.put("mchid", wxPayConfig.getMchId());
            requestMap.put("description", request.getDescription());
            requestMap.put("out_trade_no", request.getOutTradeNo());
            requestMap.put("notify_url", wxPayConfig.getNotifyUrl());

            // 订单金额
            Map<String, Object> amountMap = new HashMap<>();
            amountMap.put("total", request.getTotalAmount());
            amountMap.put("currency", "CNY");
            requestMap.put("amount", amountMap);

            // 支付者信息
            Map<String, Object> payerMap = new HashMap<>();
            payerMap.put("openid", openid); // 使用获取到的 openid
            requestMap.put("payer", payerMap);

            // 附加数据
            if (StringUtils.isNotBlank(request.getAttach())) {
                requestMap.put("attach", request.getAttach());
            }

            // 订单优惠标记
            if (StringUtils.isNotBlank(request.getGoodsTag())) {
                requestMap.put("goods_tag", request.getGoodsTag());
            }

            // 电子发票入口开放标识
            requestMap.put("support_fapiao", request.getSupportFapiao());

            // 场景信息
            if (StringUtils.isNotBlank(request.getClientIp())) {
                Map<String, Object> sceneInfo = new HashMap<>();
                sceneInfo.put("payer_client_ip", request.getClientIp());
                requestMap.put("scene_info", sceneInfo);
            }

            // 设置订单过期时间，默认2小时后过期
            LocalDateTime expireTime = LocalDateTime.now().plusHours(2);
            // 格式化为RFC3339标准格式：yyyy-MM-DDTHH:mm:ss+TIMEZONE
            String timeExpire = expireTime.atOffset(ZoneOffset.of("+08:00"))
                    .format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'+08:00'"));
            requestMap.put("time_expire", timeExpire);

            // 转换为JSON字符串
            String requestBody = objectMapper.writeValueAsString(requestMap);

            // 准备请求头
            String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
            String nonceStr = WxPaySignatureUtil.generateNonceStr();
            String url = CREATE_ORDER_URL;

            // 确保URL以斜杠开头
            if (!url.startsWith("/")) {
                url = "/" + url;
            }

            // 获取私钥
            String privateKeyContent = WxPaySignatureUtil.readPrivateKey(wxPayConfig.getPrivateKeyPath());
            PrivateKey privateKey = WxPaySignatureUtil.getPrivateKey(privateKeyContent);

            // 生成认证头
            String authorizationHeader = WxPaySignatureUtil.generateAuthorizationHeader(
                    "POST", url, timestamp, nonceStr, requestBody,
                    wxPayConfig.getMchId(), wxPayConfig.getMchSerialNo(), privateKey);

            // 设置请求头
            HttpHeaders headers = new HttpHeaders();
            headers.set("Authorization", authorizationHeader);
            headers.set("Content-Type", "application/json");
            headers.set("Accept", "application/json");
            // 加入Wechatpay-Serial头，告知微信支付本次请求将使用微信支付公钥验签
            // 注意：如果不带这个头，微信支付将使用平台证书签名
            // 根据微信支付文档显示，公钥ID格式必须是 PUB_KEY_ID_ 开头
            headers.set("Wechatpay-Serial", wxPayConfig.getPublicKeyId());

            // 发送请求
            HttpEntity<String> requestEntity = new HttpEntity<>(requestBody, headers);
            ResponseEntity<Map> responseEntity = restTemplate.exchange(
                    wxPayConfig.getDomain() + url,
                    HttpMethod.POST,
                    requestEntity,
                    Map.class
            );

            Map<String, Object> responseMap = responseEntity.getBody();
            if (responseMap == null) {
                return Result.failed("微信支付下单失败：返回为空");
            }

            if (responseMap.containsKey("code")) {
                return Result.failed("微信支付下单失败：" + responseMap.get("message"));
            }

            // 获取预支付交易会话标识
            String prepayId = (String) responseMap.get("prepay_id");
            if (StringUtils.isBlank(prepayId)) {
                return Result.failed("微信支付下单失败：未获取到prepay_id");
            }

            // 生成JSAPI支付参数
            WxPayOrderResponse response = generateJsapiPayParams(appid, prepayId, privateKey);
            response.setRawData(responseMap);

            return Result.success(response);
        } catch (Exception e) {
            log.error("微信支付下单异常", e);
            return Result.failed("微信支付下单异常：" + e.getMessage());
        }
    }

    @Override
    public Result<Map<String, Object>> queryOrder(String outTradeNo) {
        try {
            // 准备请求
            String url = String.format(QUERY_ORDER_URL, outTradeNo);
            // 确保URL路径正确，微信支付API要求商户号作为查询参数
            String queryString = "mchid=" + wxPayConfig.getMchId();
            
            // 修改：签名用的URL路径应该包含前导斜杠，保证与微信支付文档一致
            // 微信支付API要求 URL = 域名之后的请求路径，包含前导'/'
            String signUrl = url;
            // 确保URL以斜杠开头
            if (!signUrl.startsWith("/")) {
                signUrl = "/" + signUrl;
            }
            
            String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
            String nonceStr = WxPaySignatureUtil.generateNonceStr();

            // 获取私钥
            String privateKeyContent = WxPaySignatureUtil.readPrivateKey(wxPayConfig.getPrivateKeyPath());
            PrivateKey privateKey = WxPaySignatureUtil.getPrivateKey(privateKeyContent);

            // 添加日志输出，便于调试
            log.debug("签名使用的URL: {}", signUrl);
            log.debug("签名使用的查询字符串: {}", queryString);
            
            // 增加调试信息 - 验证签名是否正确
            WxPaySignatureUtil.verifyAndDebugSignature(
                    "GET", signUrl + "?" + queryString, timestamp, nonceStr, "", privateKey);
            
            // 生成认证头 - 使用正确的URL格式
            String authorizationHeader = WxPaySignatureUtil.generateAuthorizationHeader(
                    "GET", signUrl + "?" + queryString, timestamp, nonceStr, "",
                    wxPayConfig.getMchId(), wxPayConfig.getMchSerialNo(), privateKey);

            // 设置请求头
            HttpHeaders headers = new HttpHeaders();
            headers.set("Authorization", authorizationHeader);
            headers.set("Accept", "application/json");
            headers.set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");
            // 加入Wechatpay-Serial头，告知微信支付本次请求将使用微信支付公钥验签
            headers.set("Wechatpay-Serial", wxPayConfig.getPublicKeyId());
            
            // 打印请求信息，便于调试
            log.info("微信支付查询订单请求，URL: {}, Authorization: {}, 商户号: {}, 序列号: {}, 时间戳: {}, 随机串: {}",
                    wxPayConfig.getDomain() + url + "?" + queryString, 
                    authorizationHeader.substring(0, 50) + "...", 
                    wxPayConfig.getMchId(), 
                    wxPayConfig.getMchSerialNo(),
                    timestamp,
                    nonceStr);
            
            // 打印配置信息，注意敏感信息要脱敏
            log.info("微信支付配置信息，商户号: {}, 序列号: {}, 私钥路径: {}, 域名: {}", 
                    wxPayConfig.getMchId(), 
                    wxPayConfig.getMchSerialNo(), 
                    wxPayConfig.getPrivateKeyPath(),
                    wxPayConfig.getDomain());

            // 发送请求
            HttpEntity<String> requestEntity = new HttpEntity<>(headers);
            try {
                // 完整的URL应该包含域名前缀
                String fullRequestUrl = wxPayConfig.getDomain() + url + "?" + queryString;
                ResponseEntity<Map> responseEntity = restTemplate.exchange(
                        fullRequestUrl,
                        HttpMethod.GET,
                        requestEntity,
                        Map.class
                );

                Map<String, Object> responseMap = responseEntity.getBody();
                if (responseMap == null) {
                    return Result.failed("查询订单失败：返回为空");
                }

                if (responseMap.containsKey("code")) {
                    log.error("微信支付查询订单失败，错误码: {}, 错误信息: {}", 
                            responseMap.get("code"), 
                            responseMap.get("message"));
                    return Result.failed("查询订单失败：" + responseMap.get("message"));
                }

                return Result.success(responseMap);
            } catch (org.springframework.web.client.HttpStatusCodeException e) {
                // 捕获HTTP状态码异常，输出详细错误信息
                log.error("微信支付HTTP错误: 状态码={}, 错误信息={}, 响应体={}",
                    e.getStatusCode(), e.getMessage(), e.getResponseBodyAsString());
                return Result.failed("查询订单异常: 状态码=" + e.getStatusCode() + 
                         ", 错误信息=" + e.getResponseBodyAsString());
            }
        } catch (Exception e) {
            log.error("查询订单异常", e);
            return Result.failed("查询订单异常：" + e.getMessage());
        }
    }

    @Override
    public Result<Boolean> closeOrder(String outTradeNo) {
        log.info("[closeOrder] 入参 outTradeNo: {}", outTradeNo);
        log.info("[closeOrder] wxPayConfig: {}", wxPayConfig);
        if (wxPayConfig != null) {
            log.info("[closeOrder] wxPayConfig.getDomain(): {}", wxPayConfig.getDomain());
            log.info("[closeOrder] wxPayConfig.getMchId(): {}", wxPayConfig.getMchId());
            log.info("[closeOrder] wxPayConfig.getMchSerialNo(): {}", wxPayConfig.getMchSerialNo());
            log.info("[closeOrder] wxPayConfig.getPrivateKeyPath(): {}", wxPayConfig.getPrivateKeyPath());
            log.info("[closeOrder] wxPayConfig.getPublicKeyId(): {}", wxPayConfig.getPublicKeyId());
        }
        log.info("[closeOrder] restTemplate: {}", restTemplate);
        log.info("[closeOrder] objectMapper: {}", objectMapper);
        try {
            log.info("开始关闭微信支付订单: {}", outTradeNo);
            
            // 准备请求
            String url = String.format(CLOSE_ORDER_URL, outTradeNo);
            // 确保URL以斜杠开头
            if (!url.startsWith("/")) {
                url = "/" + url;
            }
            
            String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
            String nonceStr = WxPaySignatureUtil.generateNonceStr();

            // 请求体
            Map<String, String> requestMap = new HashMap<>();
            requestMap.put("mchid", wxPayConfig.getMchId());
            String requestBody = objectMapper.writeValueAsString(requestMap);
            
            log.info("关闭订单请求参数: URL={}, mchId={}, outTradeNo={}, timestamp={}, nonceStr={}", 
                    url, wxPayConfig.getMchId(), outTradeNo, timestamp, nonceStr);

            // 获取私钥
            String privateKeyContent = WxPaySignatureUtil.readPrivateKey(wxPayConfig.getPrivateKeyPath());
            PrivateKey privateKey = WxPaySignatureUtil.getPrivateKey(privateKeyContent);
            
            log.debug("成功读取私钥: {}", wxPayConfig.getPrivateKeyPath());

            // 生成认证头
            String authorizationHeader = WxPaySignatureUtil.generateAuthorizationHeader(
                    "POST", url, timestamp, nonceStr, requestBody,
                    wxPayConfig.getMchId(), wxPayConfig.getMchSerialNo(), privateKey);
            
            log.debug("生成认证头: {} (截断显示)", authorizationHeader.substring(0, Math.min(authorizationHeader.length(), 50)) + "...");

            // 设置请求头
            HttpHeaders headers = new HttpHeaders();
            headers.set("Authorization", authorizationHeader);
            headers.set("Content-Type", "application/json");
            headers.set("Accept", "application/json");
            // 加入Wechatpay-Serial头，告知微信支付本次请求将使用微信支付公钥验签
            headers.set("Wechatpay-Serial", wxPayConfig.getPublicKeyId());
            
            // 打印请求信息，便于调试
            log.info("微信支付关闭订单请求，URL: {}, 商户号: {}, 序列号: {}, 时间戳: {}, 随机串: {}",
                    wxPayConfig.getDomain() + url,
                    wxPayConfig.getMchId(), 
                    wxPayConfig.getMchSerialNo(),
                    timestamp,
                    nonceStr);
            
            log.debug("微信支付关闭订单请求体: {}", requestBody);

            // 发送请求
            HttpEntity<String> requestEntity = new HttpEntity<>(requestBody, headers);
            
            try {
                log.info("开始发送关闭订单请求: {}", wxPayConfig.getDomain() + url);
                ResponseEntity<Void> responseEntity = restTemplate.exchange(
                        wxPayConfig.getDomain() + url,
                        HttpMethod.POST,
                        requestEntity,
                        Void.class
                );

                int statusCode = responseEntity.getStatusCode().value();
                log.info("微信支付关闭订单响应: 状态码={}", statusCode);
                
                if (statusCode == 204) {
                    log.info("微信支付订单关闭成功: {}", outTradeNo);
                    return Result.success();
                } else {
                    log.error("微信支付订单关闭失败: {}, HTTP状态码: {}", outTradeNo, statusCode);
                    return Result.failed("关闭订单失败：HTTP状态码 " + statusCode);
                }
            } catch (org.springframework.web.client.HttpStatusCodeException e) {
                // 捕获HTTP状态码异常，输出详细错误信息
                log.error("微信支付关闭订单HTTP错误: 状态码={}, 错误信息={}, 响应体={}",
                        e.getStatusCode(), e.getMessage(), e.getResponseBodyAsString());
                return Result.failed("关闭订单异常: 状态码=" + e.getStatusCode() + 
                        ", 错误信息=" + e.getResponseBodyAsString());
            } catch (org.springframework.web.client.ResourceAccessException e) {
                // 连接超时等网络问题
                log.error("微信支付关闭订单网络错误: {}", e.getMessage(), e);
                return Result.failed("关闭订单网络异常: " + e.getMessage());
            }
        } catch (Exception e) {
            log.error("[closeOrder] 关闭订单异常类型: {}，异常信息: {}", e.getClass().getName(), e.getMessage(), e);
            return Result.failed("关闭订单异常: " + e.getClass().getName() + ", " + e.getMessage());
        }
    }

    @Override
    public Result<Map<String, Object>> refund(String outTradeNo, String outRefundNo, Integer amount, String reason) {
        try {
            // 准备请求
            String url = REFUND_URL;
            // 确保URL以斜杠开头
            if (!url.startsWith("/")) {
                url = "/" + url;
            }
            
            String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
            String nonceStr = WxPaySignatureUtil.generateNonceStr();

            // 请求体
            Map<String, Object> requestMap = new HashMap<>();
            requestMap.put("out_trade_no", outTradeNo);
            requestMap.put("out_refund_no", outRefundNo);

            // 金额信息
            Map<String, Object> amountMap = new HashMap<>();
            amountMap.put("refund", amount);
            amountMap.put("total", amount); // 需要查询订单获取实际金额
            amountMap.put("currency", "CNY");
            requestMap.put("amount", amountMap);

            if (StringUtils.isNotBlank(reason)) {
                requestMap.put("reason", reason);
            }

            String requestBody = objectMapper.writeValueAsString(requestMap);

            // 获取私钥
            String privateKeyContent = WxPaySignatureUtil.readPrivateKey(wxPayConfig.getPrivateKeyPath());
            PrivateKey privateKey = WxPaySignatureUtil.getPrivateKey(privateKeyContent);

            // 生成认证头
            String authorizationHeader = WxPaySignatureUtil.generateAuthorizationHeader(
                    "POST", url, timestamp, nonceStr, requestBody,
                    wxPayConfig.getMchId(), wxPayConfig.getMchSerialNo(), privateKey);

            // 设置请求头
            HttpHeaders headers = new HttpHeaders();
            headers.set("Authorization", authorizationHeader);
            headers.set("Content-Type", "application/json");
            headers.set("Accept", "application/json");
            // 加入Wechatpay-Serial头，告知微信支付本次请求将使用微信支付公钥验签
            // 注意：如果不带这个头，微信支付将使用平台证书签名
            // 根据微信支付文档显示，公钥ID格式必须是 PUB_KEY_ID_ 开头
            headers.set("Wechatpay-Serial", wxPayConfig.getPublicKeyId());

            // 发送请求
            HttpEntity<String> requestEntity = new HttpEntity<>(requestBody, headers);
            ResponseEntity<Map> responseEntity = restTemplate.exchange(
                    wxPayConfig.getDomain() + url,
                    HttpMethod.POST,
                    requestEntity,
                    Map.class
            );

            Map<String, Object> responseMap = responseEntity.getBody();
            if (responseMap == null) {
                return Result.failed("申请退款失败：返回为空");
            }

            if (responseMap.containsKey("code")) {
                return Result.failed("申请退款失败：" + responseMap.get("message"));
            }

            return Result.success(responseMap);
        } catch (Exception e) {
            log.error("申请退款异常", e);
            return Result.failed("申请退款异常：" + e.getMessage());
        }
    }

    // 在 WxPayServiceImpl.java 中修改 parsePayNotify 方法
    @Override
    public Result<Map<String, Object>> parsePayNotify(String notifyData) {
        try {
            log.info("开始处理微信支付回调通知: {}", notifyData);

            // 解析通知数据
            Map<String, Object> notifyMap = objectMapper.readValue(notifyData, Map.class);
            String eventType = (String) notifyMap.get("event_type");

            log.info("微信支付回调事件类型: {}", eventType);

            if ("TRANSACTION.SUCCESS".equals(eventType)) {
                // 处理支付成功通知
                Map<String, Object> resource = (Map<String, Object>) notifyMap.get("resource");
                if (resource == null) {
                    log.error("回调数据中缺少resource字段");
                    return Result.failed("回调数据格式错误");
                }

                // 获取加密数据
                String ciphertext = (String) resource.get("ciphertext");
                String nonce = (String) resource.get("nonce");
                String associatedData = (String) resource.get("associated_data");

                // TODO: 这里应该解密数据，但为了快速解决问题，我们先查询最近的待支付订单
                log.info("收到支付成功通知，开始处理最近的待支付订单");

                // 由于解密复杂，采用轮询方式处理最近的待支付订单
                handleRecentPayments();

                // 构造成功回复
                Map<String, Object> replyMap = new HashMap<>();
                replyMap.put("code", "SUCCESS");
                replyMap.put("message", "成功");
                replyMap.put("event_type", eventType);

                return Result.success(replyMap);
            } else {
                log.warn("未处理的回调事件类型: {}", eventType);
                Map<String, Object> replyMap = new HashMap<>();
                replyMap.put("code", "SUCCESS");
                replyMap.put("message", "事件已收到但未处理");
                return Result.success(replyMap);
            }
        } catch (Exception e) {
            log.error("解析支付通知异常", e);
            Map<String, Object> replyMap = new HashMap<>();
            replyMap.put("code", "FAIL");
            replyMap.put("message", "系统错误");
            return Result.success(replyMap);
        }
    }

    /**
     * 处理最近的待支付订单
     */
    private void handleRecentPayments() {
        try {
            // 查询最近1小时内的待支付VIP订单
            LocalDateTime oneHourAgo = LocalDateTime.now().minusHours(1);

            // 查询最近的待支付订单
            List<PaymentOrder> recentOrders = paymentOrderMapper.findRecentWaitPayOrders(oneHourAgo);

            log.info("找到 {} 个最近的待支付订单", recentOrders.size());

            for (PaymentOrder order : recentOrders) {
                try {
                    // 查询微信支付状态
                    Result<Map<String, Object>> queryResult = queryOrder(order.getOutTradeNo());

                    if (queryResult.isSuccess()) {
                        Map<String, Object> wxOrder = queryResult.getData();
                        String tradeState = (String) wxOrder.get("trade_state");

                        log.info("订单 {} 微信支付状态: {}", order.getOutTradeNo(), tradeState);

                        if ("SUCCESS".equals(tradeState)) {
                            String transactionId = (String) wxOrder.get("transaction_id");

                            log.info("检测到订单 {} 在微信端已支付成功，开始更新本地状态", order.getOutTradeNo());

                            // 更新订单状态
                            int updateCount = paymentOrderMapper.updatePaySuccess(
                                    order.getOutTradeNo(),
                                    transactionId,
                                    "SUCCESS"
                            );

                            log.info("更新订单状态结果: {} 行记录被更新", updateCount);

                            if (updateCount > 0) {
                                // 处理支付成功回调
                                if (order.getOutTradeNo().startsWith("VIP_")) {
                                    handleVipPaymentSuccess(order.getOutTradeNo(), transactionId);
                                }
                            } else {
                                log.warn("订单 {} 状态更新失败，可能已被处理", order.getOutTradeNo());
                            }
                        } else if ("CLOSED".equals(tradeState)) {
                            // 处理已关闭的订单
                            log.info("订单 {} 已关闭，更新本地状态为CLOSED", order.getOutTradeNo());
                            paymentOrderMapper.updateStatusByOutTradeNo(order.getOutTradeNo(), "CLOSED");
                        }
                    } else {
                        log.error("查询订单 {} 失败: {}", order.getOutTradeNo(), queryResult.getMessage());
                    }
                } catch (Exception e) {
                    log.error("处理订单 {} 异常", order.getOutTradeNo(), e);
                }
            }
        } catch (Exception e) {
            log.error("处理最近支付订单异常", e);
        }
    }

    /**
     * 处理VIP支付成功
     */
    private void handleVipPaymentSuccess(String outTradeNo, String transactionId) {
        try {
            log.info("开始处理VIP支付成功回调: outTradeNo={}, transactionId={}", outTradeNo, transactionId);

            // 查询订单信息
            PaymentOrder order = paymentOrderMapper.selectByOutTradeNo(outTradeNo);
            if (order == null) {
                log.error("订单不存在: {}", outTradeNo);
                return;
            }

            // 解析会员信息
            String attach = order.getAttach();
            if (attach != null && attach.startsWith("membershipOrder_")) {
                String[] parts = attach.split("_");
                if (parts.length >= 3) {
                    Long membershipId = Long.parseLong(parts[1]);
                    String subscriptionType = parts[2];

                    // 确定天数
                    int days = "YEARLY".equals(subscriptionType) ? 365 : 30;

                    log.info("准备激活会员: userId={}, membershipId={}, type={}, days={}",
                            order.getUserId(), membershipId, subscriptionType, days);

                    // 调用用户服务激活会员
                    Result<Void> activateResult = userServiceClient.activateMembership(
                            order.getUserId(),
                            membershipId.intValue(),
                            subscriptionType,
                            days,
                            "payment",
                            outTradeNo
                    );

                    if (activateResult.isSuccess()) {
                        log.info("会员激活成功: userId={}, outTradeNo={}", order.getUserId(), outTradeNo);
                    } else {
                        log.error("会员激活失败: userId={}, outTradeNo={}, error={}",
                                order.getUserId(), outTradeNo, activateResult.getMessage());
                    }
                }
            }
        } catch (Exception e) {
            log.error("处理VIP支付成功异常", e);
        }
    }

    /**
     * 根据用户ID获取微信openid
     */
    private String getOpenidByUserId(Long userId, String tradeType) {
        if (userId == null) {
            log.warn("获取openid失败: userId为空");
            return null;
        }

        log.info("尝试获取用户openid: userId={}, tradeType={}", userId, tradeType);

        try {
            Result<UserInfoResponse> userResult = userServiceClient.getUserInfo(userId);
            if (userResult.isSuccess() && userResult.getData() != null) {
                UserInfoResponse userInfo = userResult.getData(); // 直接使用 UserInfoResponse
                String openid = null;

                // 根据交易类型返回对应的openid
                if ("jsapi".equalsIgnoreCase(tradeType)) {
                    openid = userInfo.getOfficialOpenid();
                    log.info("获取用户公众号openid: {}", openid);
                } else if ("miniapp".equalsIgnoreCase(tradeType)) {
                    openid = userInfo.getMiniappOpenid();
                    log.info("获取用户小程序openid: {}", openid);
                } else {
                    // 默认情况下，尝试获取小程序openid
                    openid = userInfo.getMiniappOpenid();
                    log.info("未指定明确的交易类型，默认获取用户小程序openid: {}", openid);

                    // 如果小程序openid为空，尝试获取公众号openid
                    if (StringUtils.isBlank(openid)) {
                        openid = userInfo.getOfficialOpenid();
                        log.info("小程序openid为空，尝试获取公众号openid: {}", openid);
                    }
                }

                if (StringUtils.isBlank(openid)) {
                    log.warn("用户未绑定对应的openid: userId={}, tradeType={}, wechatBound={}",
                            userId, tradeType, userInfo.getWechatBound());

                    // 输出用户所有的openid信息以便调试
                    log.info("用户openid详情: miniapp={}, official={}, unionid={}",
                            userInfo.getMiniappOpenid(),
                            userInfo.getOfficialOpenid(),
                            userInfo.getUnionid());
                }

                return openid;
            } else {
                log.warn("通过 UserServiceClient 获取用户信息失败: userId={}, error: {}", userId, userResult.getMessage());
                return null;
            }
        } catch (Exception e) {
            log.error("调用 UserServiceClient 获取用户信息异常: userId={}", userId, e);
            return null;
        }
    }

    /**
     * 为JSAPI支付构建支付参数
     */
    private Map<String, Object> buildJsapiPayInfo(String prepayId) throws Exception {
        Map<String, Object> signParams = new HashMap<>();
        signParams.put("appId", miniappAppid);
        
        long timestamp = System.currentTimeMillis() / 1000;
        String nonceStr = generateNonceStr();
        
        signParams.put("timeStamp", String.valueOf(timestamp));
        signParams.put("nonceStr", nonceStr);
        signParams.put("package", "prepay_id=" + prepayId);
        signParams.put("signType", "RSA");
        
        // 签名字符串
        String message = miniappAppid + "\n" + timestamp + "\n" + nonceStr + "\n" + "prepay_id=" + prepayId + "\n";
        String signature = sign(message);
        
        signParams.put("paySign", signature);
        
        return signParams;
    }
    
    /**
     * 生成商户订单号
     */
    private String generateOutTradeNo(String productId) {
        // 订单号格式: 产品ID前缀 + 时间戳
        return productId + System.currentTimeMillis();
    }
    
    /**
     * 生成随机字符串
     */
    private String generateNonceStr() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    /**
     * 生成JSAPI支付参数
     *
     * @param appId      应用ID
     * @param prepayId   预支付交易会话标识
     * @param privateKey 私钥对象
     * @return JSAPI支付参数
     */
    private WxPayOrderResponse generateJsapiPayParams(String appId, String prepayId, PrivateKey privateKey) {
        WxPayOrderResponse response = new WxPayOrderResponse();
        response.setPrepayId(prepayId);
        response.setAppId(appId);

        // 时间戳
        String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
        response.setTimeStamp(timestamp);

        // 随机字符串
        String nonceStr = WxPaySignatureUtil.generateNonceStr();
        response.setNonceStr(nonceStr);

        // 订单详情扩展字符串
        String packageValue = "prepay_id=" + prepayId;
        response.setPackageValue(packageValue);

        // 签名类型
        response.setSignType("RSA");

        // 生成签名
        String paySign = WxPaySignatureUtil.generateJsapiSignature(appId, timestamp, nonceStr, packageValue, privateKey);
        response.setPaySign(paySign);

        return response;
    }

    /**
     * 生成签名
     */
    private String sign(String message) throws Exception {
        // 获取私钥
        String privateKeyContent = WxPaySignatureUtil.readPrivateKey(wxPayConfig.getPrivateKeyPath());
        PrivateKey privateKey = WxPaySignatureUtil.getPrivateKey(privateKeyContent);
        
        // 使用小程序的appid，因为这个方法主要用于JSAPI支付
        return WxPaySignatureUtil.generateJsapiSignature(miniappAppid, 
                                                   String.valueOf(System.currentTimeMillis() / 1000),
                                                   generateNonceStr(), 
                                                   message, 
                                                   privateKey);
    }
    
    /**
     * 构建微信支付请求头
     */
    private HttpHeaders buildWxPayHeaders(String method, String url, String body) throws Exception {
        // 准备请求头
        String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
        String nonceStr = WxPaySignatureUtil.generateNonceStr();

        // 获取私钥
        String privateKeyContent = WxPaySignatureUtil.readPrivateKey(wxPayConfig.getPrivateKeyPath());
        PrivateKey privateKey = WxPaySignatureUtil.getPrivateKey(privateKeyContent);

        // 确保URL不包含前导斜杠
        String signUrl = url;
        if (signUrl.startsWith("/")) {
            signUrl = signUrl.substring(1);
        }
        // 只保留相对URL路径，去除域名前缀
        if (signUrl.startsWith(wxPayConfig.getDomain())) {
            signUrl = signUrl.substring(wxPayConfig.getDomain().length());
            if (signUrl.startsWith("/")) {
                signUrl = signUrl.substring(1);
            }
        }

        // 生成认证头
        String authorizationHeader = WxPaySignatureUtil.generateAuthorizationHeader(
                method, signUrl, timestamp, nonceStr, body,
                wxPayConfig.getMchId(), wxPayConfig.getMchSerialNo(), privateKey);

        // 设置请求头
        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", authorizationHeader);
        headers.set("Content-Type", "application/json");
        headers.set("Accept", "application/json");
        headers.set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");
        // 加入Wechatpay-Serial头，告知微信支付本次请求将使用微信支付公钥验签
        headers.set("Wechatpay-Serial", wxPayConfig.getPublicKeyId());
        
        return headers;
    }

    /**
     * 获取微信支付配置
     * 
     * @return 微信支付配置对象
     */
    @Override
    public WxPayConfig getWxPayConfig() {
        return this.wxPayConfig;
    }

    @Override
    public Result<Map<String, Object>> createPaymentOrder(Long userId, Long productId, Integer amount,
                                                  String subject, String body, String payChannel,
                                                  String payType, String attach, String clientIp) {
        log.info("创建支付订单: userId={}, productId={}, amount={}, subject={}, payChannel={}, payType={}, clientIp={}",
                userId, productId, amount, subject, payChannel, payType, clientIp);

        try {
            // 1. 获取用户的 OpenID
            // 注意：这里需要确定是获取小程序openid还是公众号openid，取决于前端场景
            // 假设默认使用小程序openid，如果需要区分，payType需要更明确或增加参数
            String openid = getOpenidByUserId(userId, payType); // 使用重构后的方法
            if (StringUtils.isBlank(openid)) {
                log.error("获取用户 openid 失败: userId={}", userId);
                return Result.failed("获取用户微信openid失败，无法支付");
            }

            // 2. 生成商户订单号 (可以使用 OrderNumberUtil)
            String outTradeNo = OrderNumberUtil.generateOrderNumber(); // 或根据业务定义前缀
            log.info("生成商户订单号: {}", outTradeNo);

            // 3. 构建微信支付请求
            WxPayOrderRequest payRequest = new WxPayOrderRequest();
             // 根据支付类型决定appid
            String appid = "jsapi".equalsIgnoreCase(payType) ? mpAppid : miniappAppid;
            payRequest.setAppid(appid);
            payRequest.setUserId(userId); // 传递 userId
            payRequest.setDescription(StringUtils.isNotBlank(subject) ? subject : "商品购买");
            payRequest.setOutTradeNo(outTradeNo);
            payRequest.setNotifyUrl(wxPayConfig.getNotifyUrl());
            payRequest.setTotalAmount(amount);
            payRequest.setOpenid(openid);
            payRequest.setTradeType(payType.toUpperCase());
            payRequest.setAttach(attach);
            payRequest.setClientIp(clientIp);

            // 4. 调用微信支付服务(createOrder)创建订单
            // 注意：createOrder内部不再需要通过userId获取openid，因为已经传入
            Result<WxPayOrderResponse> wxPayResult = this.createOrder(payRequest);
            if (!wxPayResult.isSuccess()) {
                log.error("调用微信支付 createOrder 失败: {}", wxPayResult.getMessage());
                return Result.failed("微信支付下单失败: " + wxPayResult.getMessage());
            }

            // 5. 构建返回数据 (返回给调用方的信息，例如前端调起支付所需参数)
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("orderId", outTradeNo);
            resultMap.put("payInfo", wxPayResult.getData()); // 包含 prepay_id 和签名等
            log.info("支付订单创建成功，待支付: outTradeNo={}", outTradeNo);
            return Result.success(resultMap);
        } catch (Exception e) {
            log.error("创建支付订单异常", e);
            return Result.failed("创建支付订单异常: " + e.getMessage());
        }
    }
}